/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package gamesync;

/**
 *
 * @author trungdung
 */
import java.io.*;
import java.net.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.LinkedList;


public class SyncClient {
    private String server="";
    private int port=6666;
    Encrypter en=new Encrypter();
    //  Server ----> QueueReceived ----> Client
    private static LinkedList<String> QueueReceived=new LinkedList();
    
    //  Client ----> QueueSend ---->  Server
    private static LinkedList<String> QueueSend=new LinkedList();
    
    //thread execute query from queue
    Thread executeSQL = new Thread() {
        @Override
        public void run() {
            while(true) {
                try {
                    Class.forName("com.mysql.jdbc.Driver") ;
                    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/ddm", "abc123", "Khongbiet$!@#$") ;
                    Statement stmt = conn.createStatement() ;

                    while(true) {                        
                        if( QueueReceived.size() == 0 ) {
                            try {
                                sleep(2000);
                                continue;
                            } catch (InterruptedException ex) {
                                Logger.writeClientFile("Exception : SQL Executer :"+ex.toString());
                                Logger.writeClientMonitor("Exception : SQL Executer :"+ex.toString());                                
                            }
                        }
                        if (conn.isClosed()){
                            Logger.writeClientFile("SQL Connection : Sender : Retry to connect");
                            Logger.writeClientMonitor("SQL Connection : Sender : Retry to connect");                                
                            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/ddm", "abc123", "Khongbiet$!@#$") ;
                            stmt = conn.createStatement() ;                            
                        }                        
                        String query=QueueReceived.poll();
                        
                        int r=stmt.executeUpdate(query);
                            
                        //Log query statements fails, should be print to a file or a queue
                        if(r==0) {
                            //System.out.println(query);
                            Logger.writeClientFile("Query Fail : Sender : "+query);
                            Logger.writeClientMonitor("Query Fail : Sender : "+query);                                 
                        }
 
                    }
                } catch(SQLException e) {
                    Logger.writeClientFile("Exception : SQL Executer : "+e.toString());
                    Logger.writeClientMonitor("Exception : SQL Executer : "+e.toString());
                    try {
                        sleep(3000);
                    } catch (InterruptedException ex) {
                        Logger.writeClientFile("Exception : SQL Executer :"+ex.toString());
                        Logger.writeClientMonitor("Exception : SQL Executer :"+ex.toString());
                    }                               
                } catch(ClassNotFoundException e) {
                    Logger.writeClientFile("Exception : SQL Executer :"+e.toString());
                    Logger.writeClientMonitor("Exception : SQL Executer :"+e.toString());
                    try {
                        sleep(3000);
                    } catch (InterruptedException ex) {
                        Logger.writeClientFile("Exception : SQL Executer :"+ex.toString());
                        Logger.writeClientMonitor("Exception : SQL Executer :"+ex.toString());
                    }   
                }
            }
        }
    };
    
    Thread receiver=new Thread() {
        @Override
        public void run() {
                Socket echoSocket;
                
                PrintWriter out ;
                BufferedReader in ;
                
                String dataReceived;
                
                while(true) {
                    //connect to receive
                    try {
                        echoSocket = new Socket(server, port);

                        out =new PrintWriter(echoSocket.getOutputStream(), true);
                        in =new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
                        out.println("receive");        
                        while ((dataReceived = in.readLine()) != null) {
                            if (dataReceived.equals("end")) {
                                break;
                            }                    
                            String data;
                            data = en.decrypt(dataReceived);

                            //add to SQL query queue
                            QueueReceived.offer(data);
                            //System.out.println("echo: " + in.readLine());
                        }
                        echoSocket.close();
                    } catch (UnknownHostException e) {
                        //System.err.println("Don't know about host " + server);
                        //System.exit(1);
                        Logger.writeClientFile("Exception : Receiver : "+e.toString());
                        Logger.writeClientMonitor("Exception : Receiver : "+e.toString());                        
                    } catch (IOException e) {
                        //System.err.println("Couldn't get I/O for the connection to " + port);
                        //System.exit(1);
                        Logger.writeClientFile("Exception : Receiver : "+e.toString());
                        Logger.writeClientMonitor("Exception : Receiver : "+e.toString());                        
                    } 
                    
                    
                    //try to sleep 5s
                    try {
                         sleep(5000);
                         continue;
                    } catch (InterruptedException ex) {
                        Logger.writeClientFile("Exception : Receiver :"+ex.toString());
                        Logger.writeClientMonitor("Exception : Receiver :"+ex.toString());
                    }     
                }
                            
        }
    };
 
    Thread sender=new Thread() {
        @Override
        public void run() {
                Socket echoSocket;
                
                PrintWriter out ;
                BufferedReader in ;
                
                String dataReceived;
                
                while(true) {
                    try {
                        echoSocket = new Socket(server, port);

                        out =new PrintWriter(echoSocket.getOutputStream(), true);
                        in =new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
                        out.println("send");   
                        if(in.readLine().equals("OK")) {
                            String query;
                            for(int i=0;i<200;i++) {
                                query=QueueSend.poll();
                                if(query==null) {
                                    break;
                                }
                                out.println(query);
                            }
                            out.println("send");
                        }
                        echoSocket.close();
                    } catch (UnknownHostException e) {
                        //System.err.println("Don't know about host " + server);
                        //System.exit(1);
                        Logger.writeClientFile("Exception : Sender :"+e.toString());
                        Logger.writeClientMonitor("Exception : Sender :"+e.toString());                        
                    } catch (IOException e) {
                        //System.err.println("Couldn't get I/O for the connection to " + port);
                        //System.exit(1);
                        Logger.writeClientFile("Exception : Sender :"+e.toString());
                        Logger.writeClientMonitor("Exception : Sender :"+e.toString());                          
                    }       
                    
                    try {
                         sleep(5000);
                         continue;
                    } catch (InterruptedException ex) {
                        Logger.writeClientFile("Exception : Sender :"+ex.toString());
                        Logger.writeClientMonitor("Exception : Sender :"+ex.toString());
                    }
                }
                    
        }
    };
    
    //Tail MySQL log queries file
    Thread SQLLogTail = new Thread() {
        @Override
        public void run() {
            try {
                  BufferedReader reader = new BufferedReader(new FileReader("E:\\mysql.log"));
                  String line;
                  //int c=0;
                  while (true) {
                      line = reader.readLine();
                      if(line==null) {
                          try {
                              sleep(3000);
                              continue;
                          } catch(InterruptedException ex) {
                                Logger.writeClientFile("Exception : TailLog :"+ex.toString());
                                Logger.writeClientMonitor("Exception : TailLog :"+ex.toString());
                          }
                      }
                      String lowercase=line.toLowerCase();
                      if ((lowercase.contains("insert") || lowercase.contains("update")) && lowercase.contains("usertb") && line.contains("Query")) {
                          String r=line.substring(line.indexOf("Query")+5).trim();
                          //System.out.println(c+" : "+r);
                          //c++;
                          QueueSend.offer(en.encrypt(r));
                      }

                  }   
            } catch(IOException e) {
                //System.out.println(e.getMessage());
                Logger.writeClientFile("Exception : TailLog :"+e.toString());
                Logger.writeClientMonitor("Exception : TailLog :"+e.toString());                
            }            
        }
    };
            
    public void startSyncClient(){
        executeSQL.start();
        sender.start();
        receiver.start();
    }
    
    public int getQueueSendSize() {
        return(QueueSend.size());
    }
    public int getQueueReceivedSize() {
        return(QueueReceived.size());
    }
}

